import QtQuick 2.0
import QtQuick.Controls 2.15
import QtQml.Models 2.15
import "view"
import "components"

Item {
    anchors.fill: parent

    signal browseClicked()
    signal installClicked()
    signal updateClicked()
    signal preDownloadClicked()
    signal startClicked()
    signal retryClicked()
    signal cancelConfirmed()
    signal cancelRejected()
    signal repatchClicked()
    signal stopConfirmed()
    signal killWineServerClicked()
    signal checkSelfUpdateClicked()

    readonly property int uiStateLoading: 1
    readonly property int uiStateInstall: 2
    readonly property int uiStateInstalling: 3
    readonly property int uiStateUpdating: 5
    readonly property int uiStateStart: 6
    readonly property int uiStateRetry: 7
    readonly property int uiStatePatch: 8
    readonly property int uiStateRunning: 9
    readonly property int uiStateStarting: 10
    readonly property int uiStateStopping: 11
    readonly property int uiStateWrongDir: 12

    property bool hasUpdate: false
    property bool hasPreDownload: false
    property int uiState: uiStateLoading
    property alias isLogVisible: buttonLog.checked
    property alias progressText: textProgress.text
    property alias progress: progressBar.value // 0..1

    function log(message) {
        textLog.append(message)
    }

    function clearLog() {
        textLog.text = ""
    }

    function showLog() {
        buttonLog.checked = true
    }

    function confirmCancelInstall() {
        dialogCancelInstall.open()
    }

    Image {
        id: imageBackground
        anchors.fill: parent
        fillMode: Image.PreserveAspectCrop
        source: "qrc:/bg/bg.jpg"
        visible: !settings.hideBackground
    }

    Text {
        id: textVersion
        text: qsTr("Game Version:") + "\n" + (installedVersion || "?")
        anchors.right: parent.right
        anchors.top: parent.top
        anchors.topMargin: block * 0.75
        anchors.rightMargin: block
        horizontalAlignment: Text.AlignRight
        font.pixelSize: block / 1.5
        visible: !imageBackground.visible
    }

    Outline {
        id: versionOutline
        source: textVersion
        visible: imageBackground.visible
    }


    Rectangle {
        border.color: "black"
        radius: space / 4
        color: "#E0F0F0F0"
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.top: parent.top
        anchors.bottom: buttonBar.top
        anchors.margins: space
        visible: isLogVisible

        Flickable {
            id: flickable
            anchors.fill: parent

            boundsBehavior: Flickable.DragAndOvershootBounds
            flickableDirection: Flickable.VerticalFlick

            ScrollBar.vertical: ScrollBar {
                id: flickScroll
            }

            TextArea.flickable: TextArea {
                id: textLog
                width: parent.width
                height: parent.height
                readOnly: true
                wrapMode: TextArea.Wrap
                persistentSelection: true
                bottomPadding: 0
                selectByMouse: true
                color: "black"
            }


            function append(text) {
                let value = textLog.text + text
                let endPos = flickable.contentHeight * (1.0 - flickable.visibleArea.heightRatio)
                let pos = flickable.contentY

                textLog.text = value

                if (pos === endPos) {
                    flickable.contentY = endPos
                } else {
                    flickable.contentY = pos
                }
            }
        }
    }

    Item {
        id: buttonBar

        height: block + space
        anchors.left: parent.left
        anchors.right: parent.right
        anchors.bottom: parent.bottom

        ImageButton {
            id: buttonSettings
            anchors.left: parent.left
            anchors.margins: space
            icon: "settings"
            enabled: uiState != uiStateInstalling && uiState != uiStateUpdating && !isPreDownloading
            onClicked: popupSettingsMenu.open()
        }

        ImageButton {
            id: buttonLog
            anchors.left: buttonSettings.right
            anchors.margins: space
            icon: "log"
            checkable: true
            checked: true
        }

        Text {
            id: textStatus
            visible: progressBar.visible
            anchors.left: textProgress.left
            anchors.right: textProgress.right
            anchors.bottom: textProgress.top
            anchors.bottomMargin: space / 4

            text: isPreDownloading ? qsTr("Pre-downloading...")
                    : uiState == uiStateInstalling ? qsTr("Installing...")
                    : uiState == uiStateUpdating ? qsTr("Updating...")
                    : ""
        }

        Outline {
            id: textStatusOutline
            source: textStatus
            visible: textStatus.visible
        }

        Text {
            id: textProgress
            visible: progressBar.visible
            anchors.left: progressBar.left
            anchors.right: progressBar.right
            anchors.bottom: progressBar.top
            anchors.bottomMargin: space / 2
            elide: Text.ElideRight
        }

        Outline {
            id: textProgressOutline
            source: textProgress
            visible: textProgress.visible
        }


        ProgressBar {
            id: progressBar
            visible: isPreDownloading || uiState == uiStateInstalling || uiState == uiStateUpdating
            anchors.left: buttonLog.right
            anchors.right: buttonUpdate.visible ? buttonUpdate.left
                            : buttonBrowse.visible ? buttonBrowse.left
                            : buttonInstallUpdate.left
            anchors.bottom: parent.bottom
            anchors.margins: space
        }

        Button {
            id: buttonBrowse
            visible: uiState == uiStateInstall || uiState == uiStateWrongDir
            title: qsTr("Browse...")
            anchors.right: buttonInstallUpdate.left
            anchors.margins: space
            onClicked: browseClicked()
        }

        Button {
            id: buttonUpdate
            visible: hasUpdate && (uiState == uiStateStart || uiState == uiStatePatch) || hasPreDownload
            title: !hasPreDownload ? (qsTr("Update to") + " v" + availableVersion)
                    : isPreDownloading ? qsTr("Stop\nPre-Download")
                    : (qsTr("Pre-Download") + "\nv" + preDownloadVersion)
            anchors.right: buttonInstallUpdate.left
            anchors.margins: space
            onClicked: isPreDownloading ? cancelConfirmed()
                        : hasPreDownload ? preDownloadClicked() : updateClicked()
        }

        Button {
            id: buttonInstallUpdate
            title: uiState == uiStateInstall ? qsTr("Install")
                    : uiState == uiStateRetry ? qsTr("Retry")
                    : uiState == uiStateLoading ? qsTr("Loading...")
                    : uiState == uiStateInstalling ? qsTr("Cancel")
                    : uiState == uiStateUpdating ? qsTr("Cancel")
                    : uiState == uiStateStart ? (qsTr("Start") + (hasUpdate ? (" v" + localVersionLoader.version) : ""))
                    : uiState == uiStatePatch ? qsTr("Patch")
                    : uiState == uiStateRunning ? qsTr("Stop")
                    : uiState == uiStateStarting ? qsTr("Starting...")
                    : uiState == uiStateStopping ? qsTr("Stopping...")
                    : uiState == uiStateWrongDir ? qsTr("Install")
                    : ""
            anchors.right: parent.right
            anchors.margins: space
            enabled: uiState != uiStateLoading
                    && uiState != uiStateStarting
                    && uiState != uiStateStopping
                    && uiState != uiStateWrongDir
                    && (!isPreDownloading || (uiState != uiStateInstall && uiState != uiStatePatch))
            onClicked: uiState == uiStateInstall ? installClicked()
                    : uiState == uiStateInstalling ? confirmCancelInstall()
                    : uiState == uiStateUpdating ? confirmCancelInstall()
                    : uiState == uiStateStart ? startClicked()
                    : uiState == uiStateRetry ? retryClicked()
                    : uiState == uiStatePatch ? repatchClicked()
                    : uiState == uiStateRunning ? dialogStopClient.open()
                    : undefined
        }
    }

    Dialog {
        id: dialogCancelInstall
        anchors.centerIn: parent
        title: window.title
        standardButtons: Dialog.Yes | Dialog.No
        modal: true
        focus: true

        Text {
            id: textDialog
            anchors.fill: parent
            text: qsTr("Some tasks are still running. Do you wish to stop them?")
        }

        onAccepted: cancelConfirmed()
        onRejected: cancelRejected()
    }

    Dialog {
        id: dialogStopClient
        anchors.centerIn: parent
        title: window.title
        standardButtons: Dialog.Yes | Dialog.No
        modal: true
        focus: true

        Text {
            anchors.fill: parent
            text: qsTr("Please use this only as emergency option.")
                  + "\n" + qsTr("Do you wish to terminate client?")
        }

        onAccepted: stopConfirmed()
    }

    Dialog {
        id: dialogFirstRun
        anchors.centerIn: parent
        title: window.title
        standardButtons: Dialog.Ok
        modal: true
        focus: true

        Text {
            anchors.fill: parent
            text: qsTr("The game is not meant to run on Linux. It may also break at any time.\nThere's absolutely no guarantee.")
        }

        Component.onCompleted: {
            if (settings.firstRun) {
                dialogFirstRun.open()
                settings.firstRun = false
            }
        }
    }

    Dialog {
        id: dialogAbout
        anchors.centerIn: parent
        title: window.title
        standardButtons: Dialog.Ok
        modal: true
        focus: true

        Row {
            anchors.fill: parent
            spacing: space

            Image {
                id: aboutIcon
                source: "qrc:/appicon/paimon-launcher.png"
            }

            Text {
                textFormat: Text.RichText
                onLinkActivated: Qt.openUrlExternally(link)
                text: "Original workaround project: <a href='" + patchRepo + "'>Dawn</a><br/>"
                      + "<a href='" + patchRepo + "/src/master/TROUBLESHOOTING.md'>Troubleshooting page</a><br/>"
                      + "<a href='" + patchRepo + "/src/master/TWEAKS.md'>Game Tweaks</a><br/>"
                      + "<br/><br/>"
                      + "<a href='https://notabug.org/loentar/paimon-launcher/releases'>Check for new versions of launcher here</a><br/><br/>"
                      + "For bug reports please visit <br/>"
                      + "<a href='https://notabug.org/loentar/paimon-launcher/issues'>Paimon Launcher Issues</a><br/><br/>"
                      + "Copyright © Loentar 2021"
            }
        }
    }

    Script {
        id: script

        function openWineConfig() {
            execScript('client-wrapper', 'wineconfig')
        }
    }

    Popup {
        id: popupSettingsMenu

        x: buttonSettings.x
        y: parent.height - buttonSettings.height - height - space
        width: block * 5
        height: block * listMenu.model.count
        padding: 0
        focus: true
        clip: true
        closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutside
        background: Rectangle {
            color: "lightgray"
            border.color: "black"
            radius: space / 4
        }

        ListView {
            id: listMenu
            interactive: false

            anchors.fill: parent
            model: ListModel {
                ListElement { name: "browse"; text: qsTr("Change Game location...") }
                ListElement { name: "hidebg"; text: qsTr("Hide background") }
                ListElement { name: "clearlog"; text: qsTr("Clear log") }
                ListElement { name: "speedup"; text: qsTr("Speedup downloads") }
                ListElement { name: "limitdl"; text: qsTr("Limit download speed") }
                ListElement { name: "repatch"; text: qsTr("Re-apply Wine patch") }
                ListElement { name: "killwine"; text: qsTr("Kill wineserver") }
                ListElement { name: "editwine"; text: qsTr("Edit wineconfig.sh") }
                ListElement { name: "selfupdate"; text: qsTr("Check for updates...") }
                ListElement { name: "about"; text: qsTr("About...") }
            }
            delegate: Button {
                checkBox: model.name === "speedup"
                          || model.name === "limitdl"
                          || model.name === "hidebg"
                checked: (model.name === "speedup" && settings.multiConnections) ||
                         (model.name === "limitdl" && settings.limitDownload) ||
                         (model.name === "hidebg" && settings.hideBackground)
                title: model.text
                enabled: model.name !== "repatch" || !!installedVersion
                width: listMenu.width
                border.width: 0
                color: "transparent"
                horizontalAlignment: Text.AlignLeft

                onClicked: {
                    popupSettingsMenu.close()

                    switch (model.name) {
                        case "browse":
                            browseClicked()
                            break
                        case "hidebg":
                            settings.hideBackground = !settings.hideBackground
                            break
                        case "clearlog":
                            clearLog()
                            break
                        case "limitdl":
                            settings.limitDownload = !settings.limitDownload
                            break
                        case "speedup":
                            settings.multiConnections = !settings.multiConnections
                            break
                        case "repatch":
                            repatchClicked()
                            break
                        case "killwine":
                            killWineServerClicked()
                            break
                        case "editwine":
                            script.openWineConfig()
                            break
                        case "selfupdate":
                            checkSelfUpdateClicked()
                            break
                        case "about":
                            dialogAbout.open()
                            break
                    }
                }
            }
        }
    }
}
